#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QDateTime>
#include <QUdpSocket>
#include "xmlreader.h"
#include <QtConcurrent/QtConcurrentRun>
#include <QFutureWatcher>
#include <QProcess>

bool checkDeviceOnline(const QString &ip) {
    QProcess *process = new QProcess();
    QStringList arguments{"-c", "1", ip};


    process->start("ping "+ip); // 等待ping 的结果
    // process.start("ping", arguments);
    process->waitForFinished();

    QByteArray result = process->readAllStandardOutput();
    qDebug()<<result.toHex()<<result;
    if (result.contains("ttl") || result.contains("TTL")) {  // Windows/Linux响应包含ttl字段
        return true; // 设备在线
    }
    return false; // 设备不在线
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);


    QVBoxLayout *layout = new QVBoxLayout;
    delete ui->chartform->layout();
    layout->setContentsMargins(0, 0, 0, 0);
    layout->addWidget(chart);
    ui->chartform->setLayout(layout);

    chart->addSeries("real","tempretrue","time");
    chart->addSeries("target","target value","time");
    chart->showSeries("real");
    chart->longShow();

    connect(ui->refreshPort,&QPushButton::clicked,this,[=](){QtConcurrent::run(this, &MainWindow::refreshPort);}/*&MainWindow::refreshPort*/);
    connect(this, &MainWindow::updateProgressBar, ui->progressBar, &QProgressBar::setValue);
    connect(this, &MainWindow::updatePortName, [=](const QString item){
        ui->portName->addItem(item);
    });
    ui->progressBar->setStyleSheet("QProgressBar::chunk {"
                                   "background-color: green;}");


    connect(ui->connectTo,&QPushButton::clicked,this,&MainWindow::connectToPort);
    connect(ui->enableController,&QPushButton::clicked,this,&MainWindow::enableToController);
    connect(ui->saveAsTo,&QPushButton::clicked,this,&MainWindow::saveChart);
    connect(ui->clearChart,&QPushButton::clicked,this,&MainWindow::clearChart);

    connect(ui->setplcdetails,&QPushButton::clicked,this,&MainWindow::savedetailsToPlc);
    connect(ui->uploadDetails,&QPushButton::clicked,this,&MainWindow::uploadDetailsFromPlc);

    connect(ui->functionChoose,&QToolBox::currentChanged,this,&MainWindow::enableControlType);

    connect(detectTimer,&QTimer::timeout,this,&MainWindow::getTempretrue);


    connect(ui->dial,&QDial::valueChanged,this,[=](int value){ui->power->setValue(249+value*((1250-249)/99));});
    connect(ui->dial,&QDial::sliderReleased,this,[=](){ui->setPower->click();});

    connect(ui->tempSlider,&QSlider::sliderReleased,this,[=](){ui->setTemp->click();});
    connect(ui->tempSlider,&QSlider::valueChanged,this,[=](int value){ui->tempretrue->setValue(700+value*((2000-700)/99));});
    connect(controller,&Tempreture_Controller::plcErrOccuer,this,[=](){
        ui->connectTo->setText("连接");
        detectTimer->stop();
        ui->functionChoose->setEnabled(false);
    });

    connect(ui->openAT,&QRadioButton::clicked,this,&MainWindow::openATClicked);

    connect(ATTimer,&QTimer::timeout,this,[=](){
        bool sucess = controller->readDigitalMemery(142,7);
        if(sucess){
            emit ATSucessful();
            ATTimer->stop();

            ui->autoSetPidText->append("自整定成功,整定参数如下：\n");

            float p, i, d;
            controller->readFloat(112, p, 1);
            ui->autoSetPidText->append("new P值："+QString::number(p));

            controller->readFloat(120, i, 1);
            ui->autoSetPidText->append("new I值："+QString::number(i));

            controller->readFloat(124, d, 1);
            ui->autoSetPidText->append("new D值："+QString::number(d)+"\n");

            ui->autoSetPidText->append("整定参数已自动写入PLC\n结果仅供参考，具体以实际为准！\n");
            ui->openAT->click();
        }


    });





    tableModel->setHorizontalHeaderLabels({"Value","Time(s)"});
    ui->tableView->setModel(tableModel);
    QHeaderView *headerView = ui->tableView->horizontalHeader();
    headerView->setSectionResizeMode(QHeaderView::Stretch);
    tableModel->setRowCount(50);

    plctableModel->setHorizontalHeaderLabels({"参数", "地址", "值"});
    ui->plcTableView->setModel(plctableModel);

    QHeaderView *plcheaderView = ui->plcTableView->horizontalHeader();
    plcheaderView->setSectionResizeMode(QHeaderView::Stretch);
    plctableModel->setRowCount(15);
    initPLCTable();
}

MainWindow::~MainWindow()
{
    controller->disconnectToPlc();
    delete ui;
}


void MainWindow::initPLCTable(){
    QString path = QDir(QCoreApplication::applicationDirPath()).filePath("distory.xml");

    QMap<QString,QMap<QString,QString>> plcmap = Read_XML_File(path);

    QAbstractItemModel  *model = ui->plcTableView->model();
    QStandardItemModel *standardModel = qobject_cast<QStandardItemModel*>(model);

    int row = 0;
    foreach (QString key, plcmap["plc"].keys()) {
        QStandardItem *item0 = standardModel->item(row, 0);
        if (!item0) {
            item0 = new QStandardItem(key);
            standardModel->setItem(row, 0, item0);
        } else {
            item0->setText(key);
        }

        QStandardItem *item1 = standardModel->item(row, 1);
        if (!item1) {
            item1 = new QStandardItem(plcmap["plc"][key]);
            standardModel->setItem(row, 1, item1);
        } else {
            item1->setText(plcmap["plc"][key]);
        }
        row++;
    }
}

void MainWindow::savedetailsToPlc()
{
    QString path = QDir(QCoreApplication::applicationDirPath()).filePath("distory.xml");


    QAbstractItemModel  *model = ui->plcTableView->model();
    QStandardItemModel *standardModel = qobject_cast<QStandardItemModel*>(model);

    QList<QString> itemList;
    QList<int> addressList;
    QList<float> valueList;

    if (standardModel) {
        int rowCount = standardModel->rowCount();
        int columnCount = standardModel->columnCount();
        for (int row = 0; row < qMin(rowCount, 50); ++row) {
            if (1 < columnCount) {
                QStandardItem *itemItem = standardModel->item(row, 0);
                QStandardItem *addressItem = standardModel->item(row, 1);
                QStandardItem *valueItem = standardModel->item(row, 2);
                if (itemItem&&addressItem) {
                    itemList.append(itemItem->text());
                    addressList.append(addressItem->text().toInt());
                    if(valueItem)
                        valueList.append(valueItem->text().toFloat());
                    else
                        valueList.append(0);
                }
            }
        }
    } else {
        qDebug() << "获取模型失败或模型不是 QStandardItemModel 类型";
    }

    QMap<QString,QMap<QString,QString>>map;

    foreach (QString item, itemList) {
        map["plc"][item]= QString::number(addressList[itemList.indexOf(item)]);
        controller->writeFloat(addressList[itemList.indexOf(item)],valueList[itemList.indexOf(item)],1);
    }

    qDebug()<<map;

    Save_XML_File(map, path);
}

void MainWindow::uploadDetailsFromPlc(){
    QAbstractItemModel  *model = ui->plcTableView->model();
    QStandardItemModel *standardModel = qobject_cast<QStandardItemModel*>(model);


    if (standardModel) {
        int rowCount = standardModel->rowCount();
        int columnCount = standardModel->columnCount();
        for (int row = 0; row < qMin(rowCount, 50); ++row) {
            if (1 < columnCount) {
                QStandardItem *addressItem = standardModel->item(row, 1);
                QStandardItem *valueItem = standardModel->item(row, 2);
                if (addressItem) {
                    int address = addressItem->text().toInt();
                    float fValue;
                    controller->readFloat(address, fValue, 1);
                    qDebug()<<address<<fValue;

                    if (!valueItem) {
                        valueItem = new QStandardItem(QString::number(fValue));
                        standardModel->setItem(row, 2, valueItem);
                    } else {
                        valueItem->setText(QString::number(fValue));
                    }

                }
            }
        }
    } else {
        qDebug() << "获取模型失败或模型不是 QStandardItemModel 类型";
    }
}


void MainWindow::refreshPort(){
    ui->portName->clear();
    int all = 254;
    for(int i=1;i<all;i++){
        QString ip = "192.168.2."+QString::number(i);
        if(controller->connectToPlc(ip))
        {
            emit updatePortName(ip);
            emit updateProgressBar(100);
            break;
        }
        qDebug()<<ip;
        controller->disconnectToPlc();
        emit updateProgressBar(i*100/(all-1));
    }

}

void MainWindow::connectToPort(){
    controller->CurveTimer->stop();
    if(controller->openPowerControl(false))
        ui->enableController->setText("ENABLE");

    if(ui->connectTo->text()=="连接"){
        QString ip = ui->portName->currentText();
        if(controller->connectToPlc(ip)){
            ui->connectTo->setText("断开");
            detectTimer->start(200);
        }
    }else{
        ui->connectTo->setText("连接");
        detectTimer->stop();
        controller->disconnectToPlc();
        ui->functionChoose->setEnabled(false);
    }
}

void MainWindow::enableToController(){
    if(ui->enableController->text()=="ENABLE"){
        if(controller->openPowerControl(true))
        {
            ui->enableController->setText("DISABLE");
            ui->functionChoose->setEnabled(true);
        }else ui->functionChoose->setEnabled(false);
    }else{
        if(controller->openPowerControl(false))
        {
            ui->enableController->setText("ENABLE");
            ui->functionChoose->setEnabled(false);
        }else ui->functionChoose->setEnabled(false);
    }
}

void MainWindow::clearChart(){
    chart->clearAll();
    startTime = 0;
}

void MainWindow::saveChart(){
    chart->saveAllPoints("");
}

void MainWindow::getTempretrue(){
    float temp = controller->getCurrentTempretrue();
    QString CurrentTemp = QString::number(temp,'f',1);

    if(temp<700 || temp >2600)
        CurrentTemp = "NAN";

    ui->tempreture_display->setText(CurrentTemp);

    startTime += detectTimer->interval()/1000.0;
    chart->addPoint("real", QPointF(startTime, temp));

    int power = controller->getCurrentPower()*powerConversition;
    QString CurrentPower = QString::number(power,'f',1);
    ui->power_display->setText(CurrentPower);
}

void MainWindow::setPower(){
    controller->enablePidControll(false);
    float power = ui->power->value()/powerConversition;
    // ui->dial->setValue((power-249)/(1250-249)*100);
    controller->setPower(power);
    controller->CurveTimer->stop();
}

void MainWindow::setTempreture(){
    float tempretrue = ui->tempretrue->value();
    controller->setTempretrue(tempretrue);
    controller->CurveTimer->stop();
}

void MainWindow::setCurve(){
    chart->clearSeries("target");
    QAbstractItemModel  *model = ui->tableView->model();
    QStandardItemModel *standardModel = qobject_cast<QStandardItemModel*>(model);

    QList<float> valueList;
    QList<float> timeList;

    QList<QPointF> Points;

    if (standardModel) {
        int rowCount = standardModel->rowCount();
        int columnCount = standardModel->columnCount();
        for (int row = 0; row < qMin(rowCount, 50); ++row) {
            if (1 < columnCount) {
                QStandardItem *valueItem = standardModel->item(row, 0);
                QStandardItem *timeItem = standardModel->item(row, 1);
                if (valueItem&&timeItem) {

                    valueList.append(valueItem->text().toFloat());
                    timeList.append(timeItem->text().toFloat());
                }
            }
        }
    } else {
        qDebug() << "获取模型失败或模型不是 QStandardItemModel 类型";
    }
    for (int i = 0; i < valueList.length(); ++i) {
        float sum = 0;
        for (int j = 0; j < i+1; j++) {
            sum += timeList[j];
        }
        Points.append(QPointF(sum, valueList[i]));
    }
    chart->addPoints("target", Points);
    chart->showSeries("target");

    if(ui->curve_temp->isChecked())
        controller->setCurve(valueList, timeList, "temp");
    else
    {
        for (int i = 0; i < valueList.length(); ++i) {
            valueList[i]=valueList[i]/powerConversition;
        }
        controller->setCurve(valueList, timeList, "power");
    }
}

void MainWindow::openATClicked(bool clicked){
    if(clicked){
        ui->autoSetPidText->clear();
        ui->autoSetPidText->append("自整定时禁止操作软件及退出软件！！！\n");
        ui->autoSetPidText->append("开始自整定,获取初始参数如下：\n");

        float p, i, d;
        controller->readFloat(112, p, 1);
        ui->autoSetPidText->append("P值："+QString::number(p));

        controller->readFloat(120, i, 1);
        ui->autoSetPidText->append("I值："+QString::number(i));

        controller->readFloat(124, d, 1);
        ui->autoSetPidText->append("D值："+QString::number(d)+"\n");

        controller->setDigitalMemery(0,3,false);
        controller->setDigitalMemery(0,3,true);
        controller->setDigitalMemery(140,0,true);



        ATTimer->start(1000);

    }else{
        ui->autoSetPidText->append("自整定结束\n");
        ATTimer->stop();
        controller->setDigitalMemery(0,3,false);
        qDebug()<<controller->readDigitalMemery(0,3);
    }
}



void MainWindow::on_setPower_clicked()
{
    setPower();
}


void MainWindow::on_setTemp_clicked()
{
    setTempreture();
}


void MainWindow::on_setCurve_clicked()
{
    setCurve();
}

